#!/usr/bin/env python
# -*- coding: utf-8 -*-
#===============================================================================
# Copyright 2011 zod.yslin
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# 
# Author: zod.yslin
# Email: 
# File Name: list.py
# Description: 
#   -Declaration
#       list([iterable])
#       Return a list whose items are the same and in the same order as iterable‘s items.
#       iterable may be either a sequence, a container that supports iteration, or an iterator object.
#       If iterable is already a list, a copy is made and returned, similar to iterable[:].

#   -PEP 202 -- List Comprehensions
#              List comprehensions provide a concise way to create lists without 
#              resorting to use of map(), filter() and/or lambda.

#   -Looping Over Lists
# Edit History: 
#   2011-10-13    File created.
#===============================================================================
import sys
#===============================================================================
#   Declaration
#===============================================================================
print(list('abc')) # ['a', 'b', 'c']

print(list((1,2,3))) # [1, 2, 3]
print([1,2,3])

# empty list
print(list()) # []
print([])

#===============================================================================
#   PEP 202 -- List Comprehensions
#===============================================================================
print [i for i in range(10)]
# [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

print [i for i in range(20) if i%2 == 0]
# [0, 2, 4, 6, 8, 10, 12, 14, 16, 18]

nums = [1,2,3,4]
fruit = ["Apples", "Peaches", "Pears", "Bananas"]
print [(i,f) for i in nums for f in fruit]
# [(1, 'Apples'), (1, 'Peaches'), (1, 'Pears'), (1, 'Bananas'),
#  (2, 'Apples'), (2, 'Peaches'), (2, 'Pears'), (2, 'Bananas'),
#  (3, 'Apples'), (3, 'Peaches'), (3, 'Pears'), (3, 'Bananas'),
#  (4, 'Apples'), (4, 'Peaches'), (4, 'Pears'), (4, 'Bananas')]

print [(i,f) for i in nums for f in fruit if f[0] == "P"]
# [(1, 'Peaches'), (1, 'Pears'),
#  (2, 'Peaches'), (2, 'Pears'),
#  (3, 'Peaches'), (3, 'Pears'),
#  (4, 'Peaches'), (4, 'Pears')]

print [(i,f) for i in nums for f in fruit if f[0] == "P" if i%2 == 1]
# [(1, 'Peaches'), (1, 'Pears'), (3, 'Peaches'), (3, 'Pears')]

print [i for i in zip(nums,fruit) if i[0]%2==0]
# [(2, 'Peaches'), (4, 'Bananas')]

print [i*2 for i in 1,2,3]
# [2, 4, 6]

freshfruit = ['  banana', '  loganberry ', 'passion fruit  ']
print [weapon.strip() for weapon in freshfruit]
#['banana', 'loganberry', 'passion fruit']

vec = [2, 4, 6]
print [[x,x**2] for x in vec]
# [[2, 4], [4, 16], [6, 36]]

print [(x, x**2) for x in vec]
# [(2, 4), (4, 16), (6, 36)]

vec1 = [2, 4, 6]
vec2 = [4, 3, -9]
print [x*y for x in vec1 for y in vec2]
# [8, 6, -18, 16, 12, -36, 24, 18, -54]

print [vec1[i]*vec2[i] for i in range(len(vec1))]
# [8, 12, -54]

#List comprehensions are much more flexible than map() and can be applied to complex expressions and nested functions:
print [str(round(355/113.0, i)) for i in range(1,6)]
# ['3.1', '3.14', '3.142', '3.1416', '3.14159']

# Nested List Comprehensions
mat = [
        [1, 2, 3],
        [4, 5, 6],
        [7, 8, 9],
      ]

# To avoid apprehension when nesting list comprehensions, read from right to left.
print [[row[i] for row in mat] for i in [0, 1, 2]]
# [[1, 4, 7], [2, 5, 8], [3, 6, 9]]

# A more verbose version of this snippet shows the flow explicitly:
for i in [0, 1, 2]:
    for row in mat:
        print row[i],
    print

# In real world, you should prefer built-in functions to complex flow statements. The zip() function would do a great job for this use case:
print zip(*mat)
# [(1, 4, 7), (2, 5, 8), (3, 6, 9)]

#===============================================================================
#   Looping Over Lists
#===============================================================================
# The for-in statement makes it easy to loop over the items in a list:
for item in [1,2]:
    print item,
print  

# If you need both the index and the item, use the enumerate function:
for index, item in enumerate([1,2]):
    print "[%s]:%s" % (index, item)

# If you need only the index, use range and len:
for index in range(len([1,2])):
    print index

# The list object supports the iterator protocol. 
# To explicitly create an iterator, use the built-in iter function:
i = iter([1,2])
item = i.next() # fetch first value
print item
item = i.next() # fetch second value    
print item
